import java.awt.*;
import java.awt.image.*;

public class Mario extends GameObject {

	final int 				numImages 		= 14;		// Current number of images for Mario
	public BufferedImage 	images[];
	final float				gravity 		= 0.0015F;		// Gravity in Velocity/30ms
	final float				maxVelocity 	= 0.20F;		// Maximum velocity
	final float				jumpVelocity 	= -0.50F;		// Maximum velocity
	final int   			runningDiv  	= 5;		// Gravity in Velocity/30ms
	float    				xPos,yPos;					// Current position
	float    				xNext,yNext;					// Current position
	float					xVelocity, yVelocity;	// Current velocity in pixels/30ms
	boolean 				isRight     = true;
	boolean 				isJumping   = false;
	boolean 				isRunning   = false;
	boolean 				isSmall     = false;
	CollisionRect 			colRect[];
	int 					runningCount;
	int 					runningOffset;
	int 					imageIndex;
	final String            imageLocation = "/images/mario.png";			
	//  Row 0
	//	Big Mario      - offset 80,0 16x32 
	//      Row 0
   	//   - 0 standing, 
    //  - 1-3 running right, 
    //  - 4 starting to run
    //  - 5 jump
    //  - 6 crouch, 
    //  "Facing right"
    //* Mario
    //   + offset 82,32 , 12x16, spaced 16 apart
    //   Same

	Mario(){
		// Load Background image set
		ImageLoader backgroundSet = new ImageLoader();
		backgroundSet.LoadImage(imageLocation);
		images 			= new BufferedImage[numImages];
		colRect 		= new CollisionRect[numImages]; 			
        imageIndex 		= 0;
        runningCount	= 0;

		int imageNumber;
		int x, y;
		// Row 0
		for( int i = 0; i < 7; i = i + 1 ){
			x = 80 + (i * 16);
			y = 0;
			imageNumber = i;
			// Load up the image
			InitImage( imageNumber, backgroundSet.image, x , y, 16, 32);
            colRect[imageNumber] = new CollisionRect(); 			
            colRect[imageNumber].SetDimensions(true, 16, 32); 			
		}
		
		// Row 1
		for( int i = 0; i < 7; i = i + 1 ){
			x = 82 + (i * 16);
			y = 32;
			imageNumber = i + 7;
			InitImage( imageNumber, backgroundSet.image, x , y, 12, 16);
            colRect[imageNumber] = new CollisionRect(); 			
            colRect[imageNumber].SetDimensions(true, 12, 16); 			
		}
        xVelocity = 0.0F;
        yVelocity = 0.0F;
	}
	
	void SetPos( int x, int y){
		xPos = (float) x;
		yPos = (float) y;
	}
	
	int GetX( ){
		return (int) xPos;
	}

	int GetY( ){
		return (int) yPos;
	}
	
	void DrawImage(Graphics imageGraphics, int xOffset, int yOffset){
		int imageWidth;
		int imageHeight;
		int x = (int)xPos - xOffset;
		int y = (int)yPos - yOffset;
		
		imageWidth  = images[ imageIndex].getWidth();
		imageHeight = images[ imageIndex].getHeight();
		
		if( !isRight ) // Draw flipped image
                imageGraphics.drawImage(images[ imageIndex ] ,x  , y, 
                                                                x + imageWidth,y + imageHeight , 
                                                                imageWidth, 0, 0, imageHeight , null);
		else          // Draw normal image
                imageGraphics.drawImage(images[ imageIndex ] ,x  , y, 
                                                                x + imageWidth,y + imageHeight , 
                                                                0, 0, imageWidth, imageHeight , null);
        
        
	}
	
	void InitImage(int imageNumber, BufferedImage backgroundSet, int x, int y, int width, int height ){
		// InitTile - Initialize image
		images[ imageNumber] = backgroundSet.getSubimage(x , y, width, height);
	}
	
	
	void NextPosition(int newTime ){
		xNext = xPos + ( xVelocity * newTime);
		yNext = yPos + ( yVelocity * newTime);
		
		// check to see if next position is less than 0
		if(xNext < 0.0F )
			xNext = 0.0F;
                
		// Image selection
		if( isJumping ){
            imageIndex  = 5;
		}
		else if( isRunning ){
            runningCount	= runningCount + 1;
            if( (runningCount / runningDiv) < 1 )
            	runningOffset	= 0;
            else if( (runningCount / runningDiv) < 2 )
                runningOffset	= 1;
            else if( (runningCount / runningDiv) < 3 )
                runningOffset	= 2;
            else{
                runningOffset	= 0;
                runningCount	= 0;
            }
            if( isSmall)
                imageIndex = runningOffset + 1;
            else
                imageIndex = runningOffset + 1;
		}
		else{
            imageIndex = 0;
		}
		
		// Calculate for gravity
        if( yVelocity < maxVelocity)
        	yVelocity = yVelocity + (newTime * gravity);
	}
	
	// CheckBackGroundCollision
	// Determine if the next location collides
	void CheckBackGroundCollision(GameObject object){
		CollisionRect rect = object.GetColRect();
		
		if( rect.IsValid() ) // Don't check for collision against invalid col rects (sky)
		{
			int xInc;
			int yInc;
			int x = (int) xPos;
			int y = (int) yPos;
            boolean rectIsAbove, rectIsRight, rectIsLeft,  rectIsBelow; 
			
			if( xNext == xPos )
				xInc = 0;
			else if( xNext > xPos )
				xInc = 1;
			else
				xInc = -1;
			
			if( xNext == xPos )
				xInc = 0;
			else if( xNext > xPos )
				xInc = 1;
			else
				xInc = -1;
			
			while((xInc != 0) && (yInc != 0)){
				rectIsAbove    = colRect[imageIndex].IsAbove  (rect);
				rectIsRight    = colRect[imageIndex].IsRightOf(rect);
				rectIsLeft     = colRect[imageIndex].IsLeftOf (rect);
				rectIsBelow    = colRect[imageIndex].IsBelow (rect);

            // Check to see if rectangle has collided
                        if( colRect[imageIndex].CheckCollide(rect)) {
                                // Check to see if 
                                CollisionRect 	oldRect = new CollisionRect();
                                boolean 		wasAbove ;
                                boolean 		wasRight ;
                                boolean 		wasLeft  ;
                                boolean 		wasBelow ;
                        
                                // Get Old rectangle collision results
                                oldRect.CopyDimensions(colRect[imageIndex]);
                                oldRect.SetPosition(xPos, yPos);
                                wasAbove = oldRect.IsAbove  (rect);
                                wasRight = oldRect.IsRightOf(rect);
                                wasLeft  = oldRect.IsLeftOf (rect);
                                wasBelow = oldRect.IsBelow (rect);

                                // Check for hitting ground
                    if( wasBelow && !rectIsBelow ) {
                            yVelocity    = 0;			// Turn off velocity
                            isJumping   = false;		// Turn off jumping 
                            yNext	  	 = yPos;        // Set old position as the new position 
                            colRect[imageIndex].SetPosition(x, y);
                    }
                                // Check for hitting block from above
                    else if( wasAbove && !rectIsAbove ) {
                            yVelocity    = 0;			// Turn off velocity
                            isJumping   = false;		// Turn off jumping 
                            yNext	  	 = yPos;        // Set old position as the new position 
                            colRect[imageIndex].SetPosition(x, y);
                    }
                                // Check for something from the side
                    else if( (wasLeft && !rectIsLeft) || (wasRight && !rectIsRight)){
                            xVelocity = 0;
                            xNext	  = xPos;
                            if( !colRect[imageIndex].IsLeftOf(rect) )
                                    System.out.printf("Collide Left %d %d %d %d\n", rect.x, rect.y, colRect[imageIndex].x, colRect[imageIndex].y  );
                            if( !colRect[imageIndex].IsRightOf(rect) )
                                    System.out.printf("Collide Right %d %d %d %d\n", rect.x, rect.y, colRect[imageIndex].x, colRect[imageIndex].y);
                    }
                }
			}
		}
	}
	
	void Jump(){

		if( !isJumping )
			yVelocity = jumpVelocity;

         isJumping   = true;
	}

	void CommitPosition( ){
		xPos = (int) xNext;
		yPos = (int) yNext;
	}

	void RightStart(){
		xVelocity = maxVelocity;
	 	isRight = true;
	 	isRunning = true;
	}
	void LeftStart(){
		xVelocity = -maxVelocity;
	 	isRunning = true;
	 	isRight = false;
	}
	void RightStop(){
		xVelocity 		= 0;
        runningCount 	= 0;
	 	isRunning 		= false;
	}
	void LeftStop(){
		xVelocity 		= 0;
        runningCount 	= 0;
	 	isRunning 		= false;
	}
}
